package db

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"gomonitor-server/src/domain"
	"gomonitor-server/src/mylog"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"time"
)

type DbTool struct {
	db    *gorm.DB
	sqlDb *sql.DB
}

// 初始化连接
func (t *DbTool) init(username, password, hostname, port, dbName string) (*DbTool, error) {
	dbURL := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true&loc=Local", username, password, hostname, port, dbName)
	mylog.Logger.Infof("数据源连接url:%s", dbURL)
	db, err := gorm.Open(mysql.Open(dbURL), &gorm.Config{})
	//sqlDb, err := sql.Open("mysql", dbURL)
	if err != nil {
		mylog.Logger.Errorf("初始化数据库测试错误:%s", err.Error())
		return nil, err
	}
	//sqlDb.SetConnMaxLifetime(time.Minute * 3)
	//sqlDb.SetMaxOpenConns(10)
	//sqlDb.SetMaxIdleConns(10)
	sqlDb, err := db.DB()
	if err != nil {
		mylog.Logger.Errorf("数据库连接获取失败:%s", err.Error())
		return nil, err
	}
	// 测试连接
	err = sqlDb.Ping()
	if err != nil {
		mylog.Logger.Errorf("数据库ping测试错误:%s", err.Error())
		return nil, err
	} // 使用连接进行数据库操作  // ...  // 不需要手动关闭连接  // 程序退出时会自动关闭连接池 }

	sqlDb.SetMaxOpenConns(50)
	sqlDb.SetMaxIdleConns(5)
	sqlDb.SetConnMaxIdleTime(time.Duration(3) * time.Minute)

	// 自动迁移表结构
	mylog.Logger.Info("开始自动迁移表结构")
	db.AutoMigrate(&domain.HostLast{})
	//db.AutoMigrate(&domain.Host{})
	db.AutoMigrate(&domain.HostHostTag{})
	db.AutoMigrate(&domain.HostTag{})
	mylog.Logger.Info("完成自动迁移表结构")
	return &DbTool{
		db:    db,
		sqlDb: sqlDb,
	}, nil
}

// 执行查询
func (t *DbTool) Query(query string, args ...interface{}) (*sql.Rows, error) {
	mylog.Logger.Debugf("开始查询SQL:%s", query)
	stmt, err := t.sqlDb.Prepare(query)
	if err != nil {
		mylog.Logger.Errorf("查询SQL:%s预编译错误:%s", query, err)
		// 处理错误
		mylog.Logger.Error(err)
		return nil, err
	}
	defer stmt.Close()

	// 执行查询
	rows, err := stmt.Query(args...)
	if err != nil {
		mylog.Logger.Errorf("查询SQL:%s错误:%s", query, err)
		return nil, err
	}
	mylog.Logger.Infof("查询SQL:%s完成:%s", query, err)
	return rows, nil
}

// 执行更新
func (t *DbTool) Exec(query string, args ...interface{}) (sql.Result, error) {
	mylog.Logger.Debugf("开始执行SQL:%s", query)
	stmt, err := t.sqlDb.Prepare(query)
	if err != nil {
		// 处理错误
		mylog.Logger.Errorf("执行SQL:%s预编译错误:%s", query, err)
		return nil, err
	}
	result, err2 := stmt.Exec(args...)
	err = stmt.Close()
	if err != nil {
		mylog.Logger.Errorf("关闭SQL:%s错误:%s", query, err)
		return nil, err
	}
	if err2 != nil {
		mylog.Logger.Errorf("执行SQL:%s错误:%s", query, err2)
		return nil, err2
	}
	mylog.Logger.Debugf("结束执行SQL:%s", query)
	return result, nil
}

// 关闭连接
func (t *DbTool) Close() error {
	err := t.sqlDb.Close()
	if err != nil {
		return err
	}

	return nil
}
